#include <allegro.h>
#include <stdio.h>

#define GFX_W 1024
#define GFX_H 768
#define NB_IMAGES 6
#define NB_IMAGES_e 5
struct Hero {
	BITMAP * img_right[NB_IMAGES];
	BITMAP * img_left[NB_IMAGES];
	int x, y;
	int direction; // 0:right    1:left    2:up   3:down
        int shoot;//0:normal  1:fire
       int cx;int cy;int r;//cartouche
};
typedef struct Hero Hero;
////////////////////////////////////////////////////////////
struct Enemy {
	BITMAP * img_right_e[NB_IMAGES_e];
	BITMAP * img_left_e[NB_IMAGES_e];
        BITMAP * helico_right;
        BITMAP * helico_left;
        BITMAP * helico_bom;
	int e_x, e_y,helico_x,helico_y,helico_bom_x,helico_bom_y;
	int e_direction,helico_direction; // 0:right    1:left   
        int e_shoot;//0:normal  1:fire
        int e_death;//0:alive 1:dead
       //int c_x;int c_y;int cr;//cartouche
};
typedef struct Enemy Enemy;

//utils
int get_pixel(BITMAP* Buffer,int x,int y);


//Module Background
BITMAP* load_background_bmp(char chemin_background[]);
void draw_background(BITMAP *Background,BITMAP*Buffer);
void destroy_background(BITMAP * Background);

//Module hero
void load_hero(Hero *hero);
void destroy_hero(Hero *hero);
void init_hero(Hero *hero);

void move_hero_right(Hero *hero,int *compteur,BITMAP * Background);
void move_hero_left(Hero *hero,int *compteur,BITMAP * Background);
void jump_hero(Hero *hero,BITMAP * Background); //move up

void move_hero(Hero *hero,int *compteur,BITMAP * Background);
void draw_hero(Hero hero,BITMAP *Buffer, int compteur);
void gravity_hero(Hero *hero,BITMAP * Background); //move down
void shoot_hero(Hero *hero,BITMAP * Background);
//Module enemy
void load_enemy(Enemy *enemy);
void destroy_enemy(Enemy *enemy);
void init_enemy(Enemy *enemy);

void move_enemy_right(Enemy *enemy,int *compteur_e,BITMAP * Background);
void move_enemy_left(Enemy *enemy,int *compteur_e,BITMAP * Background);

void move_enemy(Enemy *enemy,int *compteur_e,BITMAP * Background);
void draw_enemy(Enemy enemy,BITMAP *Buffer, int compteur_e);
int main() {

	char chemin_background[]="../thegunners/desert.bmp";

	BITMAP *Buffer;
	BITMAP *Background=NULL;
	BITMAP *BackgroundCol=NULL;
	Hero hero;
         Enemy enemy;  
	int compteur,compteur_e;

	/* General initialization function */
	allegro_init();
	if (install_keyboard() == -1) {
		allegro_message("Error! %s", allegro_error);
		return (-1);
	}
	set_color_depth(24);
	if (set_gfx_mode(GFX_AUTODETECT_WINDOWED, GFX_W, GFX_H, 0, 0) != 0) {
		set_gfx_mode(GFX_TEXT, 0, 0, 0, 0); /* here’s the command for text mode */
		allegro_message("Unable to initialize video mode!\n%s\n", allegro_error);
		return (1);
	}

	Buffer = create_bitmap(SCREEN_W, SCREEN_H);
	//loading images
	//loading hero
	load_hero(&hero);
        //loading enemy
         load_enemy(&enemy);
	//loading background 
	Background=load_background_bmp(chemin_background);
	


	//init position & direction
	compteur = 0;
       compteur_e=0;
	init_hero(&hero);
          init_enemy(&enemy);
	while (!key[KEY_ESC]) {
		//vider le buffer
		clear_bitmap(Buffer);
		//moving hero
		move_hero(&hero,&compteur,BackgroundCol);
                //moving enemy
               move_enemy(&enemy,&compteur_e,BackgroundCol);
		//drawing background
		draw_background(Background,Buffer);
		//drawing hero
		draw_hero(hero,Buffer,compteur);
                //drawing enemy
               draw_enemy(enemy,Buffer,compteur_e);
              // collision
                       collision(&hero,&enemy);
		//blit Buffer to screen
		blit(Buffer, screen, 0, 0, 0, 0, SCREEN_W, SCREEN_H);

		if (compteur == 10000 ||compteur_e == 10000)
			{compteur = 0;compteur_e = 0;}
	}
	//destroy Hero
	destroy_hero(&hero);
         //destroy Enemy
        destroy_enemy(&enemy);
	destroy_background(Background);
	destroy_bitmap(Buffer);
	return (0);
}
END_OF_MAIN();

/*
 * module background
 */

BITMAP* load_background_bmp(char chemin_background[])
{
	BITMAP* Background;

	Background=load_bitmap(chemin_background, NULL);
	if(Background == NULL){
		set_gfx_mode(GFX_TEXT, 0, 0, 0, 0);
		allegro_message("Unable to load image !\n%s\n", allegro_error);
		return (NULL);
	}
	return (Background);

}


void draw_background(BITMAP *Background,BITMAP*Buffer)
{
	blit(Background, Buffer, 0, 0, 0, 0, SCREEN_W, SCREEN_H);
}

void destroy_background(BITMAP * Background)
{
	destroy_bitmap(Background);
}

/*
 * module hero
 */

void load_hero(Hero *hero)
{
	int i;
	char buf[50];
	for (i = 0; i < NB_IMAGES; i++) {
		sprintf(buf, "../thegunners/right%d.bmp", i);
		hero->img_right[i] = load_bitmap(buf, NULL);
		sprintf(buf, "../thegunners/left%d.bmp", i);
		hero->img_left[i] = load_bitmap(buf, NULL);
	}
}

void destroy_hero(Hero *hero)
{
	int i;
	for (i = 0; i < NB_IMAGES; i++) {
		destroy_bitmap(hero->img_right[i]);
		destroy_bitmap(hero->img_left[i]);
	}

}
void init_hero(Hero *hero)
{
	hero->direction = 0;
	hero->x = 0;
	hero->y = 530;
          hero->r = 5;
    if(hero->direction == 0)   {hero->cx =hero->x+90;}
if(hero->direction == 1)   {hero->cx =hero->x-90;}
         hero->cy = 590;
}
void move_hero_right(Hero *hero,int *compteur,BITMAP * Background)
{

	if (key[KEY_RIGHT] && (hero->x < SCREEN_W - hero->img_right[0]->w)) {
		*compteur+=1;
                hero->y = 530;
hero->cy = 590;
                (hero->cx)+=2;
		(hero->x)+=2;
		hero->direction = 0; //right
	}

}

void move_hero_left(Hero *hero,int *compteur,BITMAP * Background)
{

	if (key[KEY_LEFT] && (hero->x > 0 + hero->img_left[0]->w)) {
		*compteur+=1;
                hero->y = 530;
hero->cy = 590;
		(hero->x)-=2;
                 (hero->cx)-=2;
		hero->direction = 1; //left
	}
}
void jump_hero(Hero *hero,BITMAP * Background)
{

	if (key[KEY_Z] && (hero->y > 0) ) {
		(hero->y)-=10;
              
		hero->direction = 2; //jump
	}

}

void gravity_hero(Hero *hero,BITMAP * Background)
{

	if (key[KEY_DOWN] && (hero->y < 533) ) {
		(hero->y)+=10;
		hero->direction = 3; //down
	}

}

void shoot_hero(Hero *hero,BITMAP * Background)
{

	if (key[KEY_A]){
	
		hero->shoot = 1; //shoot
                
              if(hero->direction == 0)
                         {(hero->cx)+=10;hero->cy = 590;}
       if(hero->direction == 1)
                         {(hero->cx)-=10;hero->cy = 590;}
          if(hero->cx==1020)
                                  {hero->shoot = 0;hero->cx =hero->x+90;}
if(hero->cx==0)
                                  {hero->shoot = 0;hero->cx =hero->x-90;}

	}

}

void move_hero(Hero *hero,int *compteur,BITMAP * Background)
{
	move_hero_right(hero,compteur,Background);//move right
	move_hero_left(hero,compteur,Background);//move left
	jump_hero(hero,Background);//jump
        gravity_hero(hero,Background); //move down
        shoot_hero(hero,Background);
	
}
void draw_hero(Hero hero,BITMAP *Buffer, int compteur)
{
	static int last_direction;

	if (hero.direction == 0){ //moving right

		draw_sprite(Buffer, hero.img_right[compteur % (NB_IMAGES-3) ],hero.x, hero.y);
		last_direction=0;
                             }

         if(hero.shoot == 1)
                   {circlefill(Buffer,hero.cx,hero.cy,hero.r, makecol(0, 255, 255));

                           

                 }

	if(hero.direction == 1){ //moving left

		draw_sprite(Buffer, hero.img_left[compteur % (NB_IMAGES-3) ],hero.x, hero.y);
		last_direction=1;
	}
	if (hero.direction == 2 && last_direction==0) {	//jumping right

		draw_sprite(Buffer, hero.img_right[3],hero.x, hero.y);
	}
	if (hero.direction == 2 && last_direction==1) {	//jumping left

		draw_sprite(Buffer, hero.img_left[3],hero.x, hero.y);

	}
if (hero.direction == 3 && last_direction==0) {	//down right

		draw_sprite(Buffer, hero.img_right[4],hero.x, hero.y);
	}
	if (hero.direction == 3 && last_direction==1) {	//down left

		draw_sprite(Buffer, hero.img_left[4],hero.x, hero.y);

	}

}






int get_pixel(BITMAP* Buffer,int x,int y)
{
	int tmp;
	tmp=getpixel(Buffer,x,y);
	return((getr(tmp) + getb(tmp) + getg(tmp)) / 3);
}

/*
 * module enemy
 */
void load_enemy(Enemy *enemy)
{
	int j;
	char buff[50];
	for (j = 0; j < NB_IMAGES_e; j++) {
		sprintf(buff, "../thegunners/eright%d.bmp", j);
		enemy->img_right_e[j] = load_bitmap(buff, NULL);
		sprintf(buff, "../thegunners/eleft%d.bmp", j);
		enemy->img_left_e[j] = load_bitmap(buff, NULL);
	}
       enemy->helico_right=load_bitmap("./tayara-d-r.bmp", NULL);
         enemy->helico_left=load_bitmap("./tayara-d-l.bmp", NULL);
enemy->helico_bom=load_bitmap("./bombe.bmp", NULL);
}

void destroy_enemy(Enemy *enemy)
{
	int i;
	for (i = 0; i < NB_IMAGES_e; i++) {
		destroy_bitmap(enemy->img_right_e[i]);
		destroy_bitmap(enemy->img_left_e[i]);
	}

destroy_bitmap(enemy->helico_right);
destroy_bitmap(enemy->helico_left);
destroy_bitmap(enemy->helico_bom);
}

void init_enemy(Enemy *enemy)
{
	enemy->e_direction = 1;
        enemy->e_death = 0;
	enemy->e_x = 530;
	enemy->e_y = 530;
        enemy->helico_x=1024;
        enemy->helico_y=50;
       enemy->helico_bom_x= enemy->helico_x + 150;
        enemy->helico_bom_y=enemy->helico_y + 150;
        enemy->helico_direction=1;
       // enemy->c_r = 5;
    /*if(enemy->e_direction == 0)   {enemy->c_x =enemy->e_x+90;}
if(enemy->e_direction == 1)   {enemy->c_x =enemy->e_x-90;}
         enemy->c_y = 600;*/
}

void move_enemy_right(Enemy *enemy,int *compteur_e,BITMAP * Background)
{

	if(enemy->e_direction == 0 && enemy->e_death == 0 ) {
		*compteur_e+=1;
                enemy->e_y = 530;
		(enemy->e_x)+=1;
		
	}
/////////////////////////////////////////////////
if(enemy->helico_direction == 0) {
		
                enemy->helico_y = 100;
		(enemy->helico_x)+=1;
                (enemy->helico_bom_x)+=1;
                 (enemy->helico_bom_y)+=1;
                                    
	}
                                                if(enemy->helico_x==10)
		                               {(enemy->helico_bom_y)+=1;}
     if (enemy->e_x == 1000)
{enemy->e_direction = 1;}
                      if (enemy->helico_x == 1024)
                      {enemy->helico_direction = 1;}
if(enemy->helico_bom_y ==768)
{enemy->helico_bom_y= enemy->helico_y + 150;}
////////////////////////////////////////////////////////
}

void move_enemy_left(Enemy *enemy,int *compteur_e,BITMAP * Background)
{

     

	if(enemy->e_direction == 1 && enemy->e_death == 0) {
		*compteur_e+=1;
                enemy->e_y = 530;
		(enemy->e_x)-=1;
		
	}
///////////////////////////////////////////
  if(enemy->helico_direction == 1) {
		
                enemy->helico_y = 100;
		(enemy->helico_x)-=1;
                (enemy->helico_bom_x)-=1;
		(enemy->helico_bom_y)+=1;
	        }
                    if(enemy->helico_x==800)
		          {(enemy->helico_bom_y)+=1;}
  if (enemy->e_x ==100)
{enemy->e_direction = 0;}
                        if (enemy->helico_x ==0)
                               {enemy->helico_direction = 0;}



if(enemy->helico_bom_y ==768)
{enemy->helico_bom_y= enemy->helico_y + 150;}
///////////////////////////////////////////////////
}

void move_enemy(Enemy *enemy,int *compteur_e,BITMAP * Background)
{
	move_enemy_right(enemy,compteur_e,Background);//move right
	move_enemy_left(enemy,compteur_e,Background);//move left
	
}


void draw_enemy(Enemy enemy,BITMAP *Buffer, int compteur_e)
{

if(enemy.e_direction == 1){ //moving left
draw_sprite(Buffer, enemy.img_left_e[compteur_e % (NB_IMAGES_e-2) ],enemy.e_x, enemy.e_y);
//draw_sprite(Buffer, enemy.img_left_e[compteur_e % (NB_IMAGES_e-2) ],enemy.e_x + 200, enemy.e_y);
//draw_sprite(Buffer, enemy.img_left_e[compteur_e % (NB_IMAGES_e-2) ],enemy.e_x +400, enemy.e_y);
	}
if(enemy.helico_direction == 1){ //moving helico left
draw_sprite(Buffer,enemy.helico_left,enemy.helico_x, enemy.helico_y);
draw_sprite(Buffer,enemy.helico_bom,enemy.helico_bom_x, enemy.helico_bom_y);
}
if (enemy.e_direction == 0){ //moving right
draw_sprite(Buffer, enemy.img_right_e[compteur_e % (NB_IMAGES_e-2) ],enemy.e_x, enemy.e_y);
//draw_sprite(Buffer, enemy.img_right_e[compteur_e % (NB_IMAGES_e-2) ],enemy.e_x+200, enemy.e_y);
//draw_sprite(Buffer, enemy.img_right_e[compteur_e % (NB_IMAGES_e-2) ],enemy.e_x+400, enemy.e_y);
}
if(enemy.helico_direction == 0){ //moving helico right
draw_sprite(Buffer,enemy.helico_right,enemy.helico_x, enemy.helico_y);
draw_sprite(Buffer,enemy.helico_bom,enemy.helico_bom_x, enemy.helico_bom_y);

}
if(enemy.e_death == 1 && enemy.e_direction == 1){ //death left
draw_sprite(Buffer,enemy.img_left_e[4],enemy.e_x, enemy.e_y+60);
}
if(enemy.e_death == 1 && enemy.e_direction == 0){ //death right
draw_sprite(Buffer,enemy.img_right_e[4],enemy.e_x, enemy.e_y+60);
}

}

/*
 * module collision
 */

void collision(Hero *hero,Enemy *enemy)
{
    int sprite1_x= enemy->e_x;
    int sprite1_y= enemy->e_y;
    int sprite1_w= enemy->e_x + 90 - sprite1_x;//
    int sprite1_h= enemy->e_y + 120 - sprite1_y;//

    int sprite2_x= hero->cx - (hero->r);
    int sprite2_y= hero->cy - (hero->r);
    int sprite2_w= (hero->cx + (hero->r)) - sprite2_x;//
    int sprite2_h= (hero->cy + (hero->r)) - sprite2_y;//


    
    if (!bounding_box_collision(sprite1_x, sprite1_y, sprite1_w, sprite1_h,
                                sprite2_x, sprite2_y, sprite2_w, sprite2_h) )
    {
        enemy->e_death=0;
    }
    else
    {
        enemy->e_death=1;
        
	
    }
}



int bounding_box_collision(int sprite1_x, int sprite1_y, int sprite1_w,
                           int sprite1_h, int sprite2_x, int sprite2_y, int sprite2_w,
                           int sprite2_h)
{
    if ((sprite1_x > sprite2_x + sprite2_w - 1) || // is Sprite1 on the right side of Sprite2?
            (sprite1_y > sprite2_y + sprite2_h - 1) || // is b1 under b2?
            (sprite2_x > sprite1_x + sprite1_w - 1) || // is b2 on the right side of b1?
            (sprite2_y > sprite1_y + sprite1_h - 1)) // is b2 under b1?
    {
        // no collision
        return 0;
    }

    // collision
    return 1;
}

























